using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace org.synthful.Windows.Native
{
    /// <summary>
    /// Offered under Apache Public Licence 2.0
    /// synthful.org
    /// blessedgeek [@] synthful.org
    /// </summary>
    public class NativeIconPtrs
    {
        [DllImport("Shell32.dll")]
        extern static public int ExtractIconEx(
            string libName, int iconIndex,
            IntPtr[] largeIcon, IntPtr[] smallIcon, int nIcons
        );

        static public int getIconCount(string libname)
        {
            return ExtractIconEx(libname, -1, null, null, 0);
        }

        static public NativeIconPtrs getIcons(
                    string libname, int iconIndex, int iconCount)
        {
            NativeIconPtrs nix = new NativeIconPtrs();

            nix.LargeIcon = new IntPtr[iconCount];
            nix.SmallIcon = new IntPtr[iconCount];

            iconCount = ExtractIconEx(libname, 0, nix.LargeIcon, nix.SmallIcon, iconCount);
            if (iconCount <= 0)
                return null;
            return nix;
        }

        public IntPtr[] LargeIcon, SmallIcon;
    }

    public class NativeIcons
    {
        static public NativeIcons[] getIcons(string libname, int iconIndex, int iconCount)
        {
            NativeIconPtrs nix = NativeIconPtrs.getIcons(libname, iconIndex, iconCount);

            NativeIcons[] icons = new NativeIcons[iconCount];
            for (int i = 0; i < iconCount; i++)
            {
                try
                {
                    icons[i] = new NativeIcons();
                    icons[i].Large = Icon.FromHandle(nix.LargeIcon[i]);
                    icons[i].Small = Icon.FromHandle(nix.SmallIcon[i]);
                }
                catch { }
            }

            return icons;
        }
        
        public Icon Large;
        public Icon Small;

    }

    public class NativeIconImages
    {
        static public NativeIconImages[] getIcons(string libname, int iconIndex, int iconCount)
        {
            NativeIconPtrs nix = NativeIconPtrs.getIcons(libname, iconIndex, iconCount);

            NativeIconImages[] icons = new NativeIconImages[iconCount];
            for (int i = 0; i < iconCount; i++)
            {
                try
                {
                    icons[i] = new NativeIconImages();
                    icons[i].Large = Icon.FromHandle(nix.LargeIcon[i]).ToBitmap();
                    icons[i].Small = Icon.FromHandle(nix.SmallIcon[i]).ToBitmap();
                }
                catch { }
            }

            return icons;
        }
        
        public Image Large;
        public Image Small;

    }

    public class NativeIconImageLists
    {
        public NativeIconImageLists()
        {
            this.LargeIcons = new ImageList();
            this.LargeIcons.ImageSize = new Size(32, 32);
            this.SmallIcons = new ImageList();
            this.Tags = new List<string>();
        }

        static public NativeIconImageLists getIcons(string libname, int iconIndex, int iconCount)
        {
            NativeIconPtrs nix = NativeIconPtrs.getIcons(libname, iconIndex, iconCount);
            NativeIconImageLists niz = new NativeIconImageLists();

            string[] elemnames = libname.Split('/', '\\');
            string leafname = elemnames[elemnames.Length - 1];

            for (int i = 0; i < iconCount; i++)
            {
                Image large = null;
                Image small = null;

                try
                {
                    large = Icon.FromHandle(nix.LargeIcon[i]).ToBitmap();
                    small = Icon.FromHandle(nix.SmallIcon[i]).ToBitmap();
                }
                catch { }

                niz.LargeIcons.Images.Add(large);
                niz.SmallIcons.Images.Add(small);
                niz.Tags.Add(leafname);
            }

            return niz;
        }

        static public NativeIconImageLists getIcons(string path)
        {
            return getIcons(null, path);
        }

        static public NativeIconImageLists getIcons(
            NativeIconImageLists niz, string path)
        {
            if (niz == null)
                niz = new NativeIconImageLists();

            string[] elemnames = path.Split('/', '\\');
            string leafname = elemnames[elemnames.Length - 1];

            Image img = Image.FromFile(path);
            niz.LargeIcons.Images.Add(img);
            niz.SmallIcons.Images.Add(img);

            niz.Tags.Add(leafname);
            return niz;
        }

        public ImageList LargeIcons;
        public ImageList SmallIcons;
        public List<string> Tags;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct IconFileTable
    {
        public byte Width;
        public byte Height;
        public byte ColorCount;
        public byte Reserved;
        public ushort Planes;
        public ushort BitCount;
        public uint BytesInRes;
        public uint ImageOffset;
    }
}
